package com.sprite.framework.entity.mapper;

import java.io.File;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.sprite.framework.entity.EntityException;
import com.sprite.framework.entity.DataScriptStatement;
import com.sprite.framework.entity.mapper.reolver.NodeParser;
import com.sprite.framework.entity.mapper.reolver.Parser;
import com.sprite.framework.entity.mapper.reolver.StatementResolver;
import com.sprite.framework.entity.util.OrmConfig;
import com.sprite.utils.UtilURL;
import com.sprite.utils.UtilXml;
import com.sprite.utils.cache.UtilCache;

public class DefaultStatementDelegator implements StatementDelegator{

	private static UtilCache<StatementMapper> mapperCache = UtilCache.createUtilCache("_mapper_cache_");
	
	public static DefaultStatementDelegator DELEGATOR_INS = new DefaultStatementDelegator();
	
	public DataScriptStatement resolve(String statement, Object param) {
		StatementMapper mapper = getMapper(statement);
		
		if(mapper == null){
			throw new EntityException("not found statement: "+statement);
		}
		return mapper.mapper(param);
	}
	
	public StatementMapper getMapper(String statement){
		StatementMapper mapper = mapperCache.get(statement);
		if(mapper != null && OrmConfig.CACHED_MAPPER){
			return mapper;
		}
		
		int index = statement.lastIndexOf('.');
		String resource = statement;
		if(index > 0) {
			resource = statement.substring(0, index);
		}
		try {
			Document doc = UtilXml.readXmlDocument(UtilURL.fromResource(resource.replace(".", File.separator)+".xml"));
			if(doc == null) {
				return null;
			}
			List<Element> elList =UtilXml.childElementList(doc.getDocumentElement());
		
			for(Element el: elList){
				StatementMapper statementMapper = StatementResolver.reolve(el, resource);
				mapperCache.put(statementMapper.getStatementId(), statementMapper);
				if(statementMapper.getStatementId().equals(statement)){
					mapper = statementMapper;
				}
			}
		} catch (Exception e) {
			throw new EntityException(e);
		} 
		return mapper;
	}

	public void addNodeParsers(List<NodeParser> parsers) {
		for(NodeParser parser: parsers){
			Parser.register(parser);
		}
	}

	public StatementScript makeScript(String statement, Object param) {
		StatementScript statementScript = new StatementScript(statement, this);
		statementScript.setParam(param);
		
		return statementScript;
	}
}
